<template>
  <div class="jcx-form-table" ref="jcxFormTableRef">
    <el-table :data="data" ref="tableRef" border :row-style="myFormTableRowStyle">
      <el-table-column type="index" width="50" fixed="left">
        <template #header>
          <el-button v-if="!hideAdd" :disabled="disabledAdd" type="primary" size="small" plain circle
                     icon="el-icon-plus" @click="rowAdd"></el-button>
          <slot name="header" v-if="hideAdd"></slot>
        </template>
        <template #default="scope">
          <div :class="['jcx-form-table-handle', {'jcx-form-table-handle-delete':!hideDelete}]">
            <span>{{ scope.$index + 1 }}</span>
            <el-button v-if="!hideDelete" :disabled="disabledDelete" type="danger" size="small" plain circle
                       icon="el-icon-delete" @click="rowDel(scope.row, scope.$index)"></el-button>
            <slot name="left" v-if="hideDelete"></slot>
          </div>
        </template>
      </el-table-column>
      <el-table-column label="序" width="40" align="center" v-if="dragSort">
        <template #default>
          <div class="move" style="cursor: move;">
            <el-icon-d-caret style="width: 1em; height: 1em;"></el-icon-d-caret>
          </div>
        </template>
      </el-table-column>
      <slot></slot>
      <template #empty>
        {{ placeholder }}
      </template>
    </el-table>
  </div>
</template>

<script setup>
import Sortable from 'sortablejs'
import {ref, onMounted, watch, nextTick} from "vue";

const data = ref([]);
const jcxFormTableRef = ref(null);
const tableRef = ref(null);

const props = defineProps({
  modelValue: {
    type: Array,
    default: () => []
  },
  addTemplate: {
    type: Object,
    default: () => {
    }
  },
  placeholder: {
    type: String,
    default: "暂无数据"
  },
  dragSort: {
    type: Boolean,
    default: false
  },
  sortField: {
    type: String,
    default: "sort"
  },
  hideAdd: {
    type: Boolean,
    default: false
  },
  disabledAdd: {
    type: Boolean,
    default: false
  },
  hideDelete: {
    type: Boolean,
    default: false
  },
  disabledDelete: {
    type: Boolean,
    default: false
  },
  formTableRowStyle: {
    type: Function,
    default: () => {
    }
  },
});

const emit = defineEmits(['update:modelValue', 'formTableRowStyle']);

onMounted(() => {
  data.value = props.modelValue
  if (props.dragSort) {
    rowDrop()
  }
});

watch(() => props.modelValue, () => data.value = props.modelValue);

watch(() => data.value, () => emit('update:modelValue', data.value));

const myFormTableRowStyle = (row) => {
  return props.formTableRowStyle ? props.formTableRowStyle(row) : {};
}

const rowDrop = () => {
  const tbody = tableRef.value.$el.querySelector('.el-table__body-wrapper tbody')
  Sortable.create(tbody, {
    handle: ".move",
    animation: 300,
    ghostClass: "ghost",
    onEnd({newIndex, oldIndex}) {
      data.value.splice(newIndex, 0, data.value.splice(oldIndex, 1)[0])
      data.value.forEach((item, index) => {
        item[props.sortField] = (index + 1)
      })
      const newArray = data.value.slice(0)
      const tmpHeight = jcxFormTableRef.value.offsetHeight
      jcxFormTableRef.value.style.setProperty('height', tmpHeight + 'px')
      data.value = []
      nextTick(() => {
        data.value = newArray;
        nextTick(() => {
          jcxFormTableRef.value.style.removeProperty('height')
        })
      })
    }
  })
}

const rowAdd = () => {
  const temp = JSON.parse(JSON.stringify(props.addTemplate))
  data.value.push(temp)
}

const rowDel = (row, index) => {
  data.value.splice(index, 1)
}

const pushRow = (row) => {
  const temp = row || JSON.parse(JSON.stringify(props.addTemplate))
  data.value.push(temp)
}

const deleteRow = (index) => {
  data.value.splice(index, 1)
}

const deleteRowById = (key, value) => {
  data.value = data.value.filter(obj => obj[key] !== value);
}

const clear = () => {
  data.value = [];
}

defineExpose({
  clear,
  pushRow,
  deleteRow,
  deleteRowById,
})
</script>

<style scoped>
.jcx-form-table {
  width: 100%;
}

.jcx-form-table .jcx-form-table-handle {
  text-align: center;
}

.jcx-form-table .jcx-form-table-handle span {
  display: inline-block;
}

.jcx-form-table .jcx-form-table-handle button {
  display: none;
}

.jcx-form-table .hover-row .jcx-form-table-handle-delete span {
  display: none;
}

.jcx-form-table .hover-row .jcx-form-table-handle-delete button {
  display: inline-block;
}

.jcx-form-table .move {
  text-align: center;
  font-size: 14px;
  margin-top: 3px;
}
</style>
